package js.web.center.web.servlet;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;

import javax.script.ScriptException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.eclipse.jetty.server.Request;

import js.web.center.core.config.JsWebConfig;
import js.web.center.script.core.JsWebScriptEngineCore;
import js.web.center.utils.JsWebScriptHandlerCacheUtils;
import js.web.center.utils.JsWebSyncCtrlUtils;
import js.web.center.utils.JsWebVelocityUtils;

/**
 * 
 * @author dowell
 *
 */
public class JsWebServletHanlder extends HttpServlet {
	private static final long serialVersionUID = 4426475504307680457L;
	private static Logger logger = Logger.getLogger(JsWebServletHanlder.class);

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doRun(request, response);
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doRun(request, response);
	}
	public void loadJs(String path){
		
	}
	private void doRun(HttpServletRequest request, HttpServletResponse response) {
		String fun = request.getParameter(JsWebConfig.servletFunName);
		if (fun == null) {
			return;
		}
		response.setHeader("Access-Control-Allow-Origin", "*");
		response.setHeader("Access-Control-Allow-Methods", "*");
		response.setHeader("Access-Control-Max-Age", "3600");
		response.setHeader("Access-Control-Allow-Headers", "*");
		response.setHeader("Access-Control-Allow-Credentials", "true");
		JsWebScriptEngineCore engineCore = null;
		if (JsWebScriptHandlerCacheUtils.hashMap.containsKey(fun)) {
			engineCore = JsWebScriptHandlerCacheUtils.hashMap.get(fun);
		} else {
			engineCore = new JsWebScriptEngineCore();
			try {
				String nowPath = JsWebConfig.WEB + fun;
				engineCore.init(JsWebConfig.LIBS_BASE);
				engineCore.init(nowPath);
				engineCore.appParams(JsWebConfig.SELF, this);
				engineCore.appParams(JsWebConfig.PARENT, engineCore);
				JsWebScriptHandlerCacheUtils.hashMap.put(fun, engineCore);
			} catch (ScriptException e) {
				send(response, JsWebConfig.REEOR_404);
				logger.error("JsWebServletHanlder ERROR:{}", e);
				return;
			} catch (FileNotFoundException e) {
				send(response, JsWebConfig.REEOR_404);
				logger.error("JsWebServletHanlder ERROR:{}", e);
				return;
			}
		}
		response.setContentType(JsWebConfig.HTML_CONTENT_TYPE);
		response.setCharacterEncoding(JsWebConfig.DEFAULT_CHAR_CODE);
		try {
			String sessioinId = null;
			if (JsWebConfig.openSyn == 1) {
				sessioinId = request.getSession().getId();
			}
			HttpSession session = request.getSession();
			session.setMaxInactiveInterval((int) (JsWebConfig.webSessionOutTime / 1000));
			if (sessioinId != null) {
				Object sessionObject = JsWebSyncCtrlUtils.getSessionObject(sessioinId);
				if (sessionObject != null) {
					synchronized (sessionObject) {
						engineCore.function(JsWebConfig.HANDLER, request, response);
					}
				} else {
					engineCore.function(JsWebConfig.HANDLER, request, response);
				}
			} else {
				engineCore.function(JsWebConfig.HANDLER, request, response);
			}
		} catch (ScriptException e) {
			send(response, JsWebConfig.REEOR_404);
			logger.error("JsWebServletHanlder ERROR:{}", e);
		} catch (NoSuchMethodException e) {
			send(response, JsWebConfig.REEOR_404);
			logger.error("JsWebServletHanlder ERROR:{}", e);
		}
	}

	/**
	 * js加载路径
	 * 
	 * @return
	 */
	public String loadPath() {
		return JsWebConfig.rootPath + JsWebConfig.BASE_SIGN + JsWebScriptEngineCore.basePath;
	}

	/**
	 * 调用其他js域内容
	 * 
	 * @param target
	 *            访问路径(例：web/指定js内容;libs/指定js内容)
	 * @param funName
	 *            调用方法
	 * @param params
	 *            参数
	 * @return
	 */
	public Object runWebPage(String target, String funName, Object... params) {
		JsWebScriptEngineCore engineCore = null;
		if (JsWebScriptHandlerCacheUtils.hashMap.containsKey(target)) {
			engineCore = JsWebScriptHandlerCacheUtils.hashMap.get(target);
		} else {
			engineCore = new JsWebScriptEngineCore();
			try {
				String nowPath = target;
				engineCore.init(nowPath);
				engineCore.appParams(JsWebConfig.SELF, this);
				engineCore.appParams(JsWebConfig.PARENT, engineCore);
				JsWebScriptHandlerCacheUtils.hashMap.put(target, engineCore);
			} catch (ScriptException e) {
				logger.error("JsWebServletHanlder ERROR:{}", e);
				return null;
			} catch (FileNotFoundException e) {
				logger.error("JsWebServletHanlder ERROR:{}", e);
				return null;
			}
		}
		try {
			return engineCore.function(funName, params);
		} catch (NoSuchMethodException e) {
			logger.error("JsWebServletHanlder ERROR:{}", e);
		} catch (ScriptException e) {
			logger.error("JsWebServletHanlder ERROR:{}", e);
		}
		return null;
	}

	/**
	 * 获取保存对象
	 * 
	 * @param request
	 * @return
	 */
	public HashMap<String, Object> getSessionMap(Request request) {
		String sessionId = request.getSession().getId();
		if (sessionId != null) {
			return JsWebSyncCtrlUtils.getSessionMap(sessionId);
		}
		return null;
	}

	/**
	 * 运行线程
	 * 
	 * @param engineCore
	 *            当前后在js域
	 * @param fun
	 *            执行方法
	 * @param params
	 *            传入参数
	 */
	public void runThread(final JsWebScriptEngineCore engineCore, final String fun, final Object... params) {
		JsWebSyncCtrlUtils.executor.execute(new Runnable() {
			@Override
			public void run() {
				try {
					engineCore.function(fun, params);
				} catch (NoSuchMethodException e) {
					logger.error("JsWebServletHanlder ERROR:{}", e);
				} catch (ScriptException e) {
					logger.error("JsWebServletHanlder ERROR:{}", e);
				}
			}
		});
	}

	/**
	 * 日志输出
	 * 
	 * @param object
	 *            打印对象
	 */
	public void log(Object object) {
		logger.info(object);
	}

	/**
	 * 发送Velocity模板数据
	 * 
	 * @param path
	 *            模板路径
	 * @param response
	 * @param context
	 * @throws IOException
	 */
	public void sendVty(String path, HttpServletResponse response, VelocityContext context) throws IOException {
		VelocityEngine velocityEngine = JsWebVelocityUtils.getVelocityEngine();
		StringWriter writer = new StringWriter();
		try {
			velocityEngine.mergeTemplate(path, JsWebConfig.DEFAULT_CHAR_CODE, context, writer);
		} catch (ResourceNotFoundException e) {
			e.printStackTrace();
		} catch (ParseErrorException e) {
			e.printStackTrace();
		} catch (MethodInvocationException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		response.getWriter().append(writer.toString()).flush();
	}

	/**
	 * 生成模板上下文
	 * 
	 * @return
	 */
	public VelocityContext context() {
		return new VelocityContext();
	}

	/**
	 * 发送消息到客户端
	 * 
	 * @param response
	 * @param info
	 *            发送消息内容
	 * @throws IOException
	 */
	public void send(HttpServletResponse response, Object info) {
		if (JsWebConfig.REEOR_404.equals(info.toString()) && JsWebConfig.lostErrorUrl.length() > 0) {
			try {
				response.sendRedirect(JsWebConfig.lostErrorUrl);
			} catch (IOException e) {
				logger.error("JsWebServletHanlder ERROR:{}", e);
			}
			return;
		}
		try {
			response.getWriter().append(info.toString()).flush();
		} catch (IOException e) {
			logger.error("JsWebServletHanlder ERROR:{}", e);
		}
	}
}
